package org.springboot3.project.demoapi.service;

import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.logger.FluentLogger;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.service.GenericService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Service
public class TestService {

    private static final Logger log = LoggerFactory.getLogger(TestService.class);

    private static String DUBBO_DEFAULT_APPLICATION_NAME = "shenyu_proxy";

    public String test(String key) {
        log.info("Test key:{}", key);
        return "success";
    }

    public String testInvokeDubbo2(String key) {
        ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-consumer");
        applicationConfig.setQosEnable(false);
        applicationConfig.setRegisterConsumer(true);

        RegistryConfig registryConfigItem = new RegistryConfig();
        registryConfigItem.setId("dubbo-consumer");
        registryConfigItem.setRegister(false);
//        registryConfigItem.setAddress("nacos://172.16.22.22:8848?namespace=local_weiwei2&username=nacos&password=expos_nacos");
        registryConfigItem.setProtocol("nacos");
        registryConfigItem.setAddress("172.16.22.22:8848");
        registryConfigItem.setUsername("nacos");
        registryConfigItem.setPassword("expos_nacos");
        Map<String, String> registryParameters = new HashMap<>();
        registryParameters.put("namespace", "local_weiwei");
        registryConfigItem.setParameters(registryParameters);

        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.refresh();
        consumerConfig.setRetries(0);
        consumerConfig.setTimeout(3000);

        ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
        reference.setGeneric("true");
        reference.setAsync(true);

        reference.setApplication(applicationConfig);
        reference.setRegistry(registryConfigItem);
        reference.setConsumer(consumerConfig);

        reference.setInterface("org.springboot3.project.demoapi.DemoService");
        reference.setVersion("1.0");
        // default protocol is dubbo
        reference.setProtocol(CommonConstants.DUBBO);
        reference.setCheck(false);


        Map<String, String> parameters = new HashMap<>(2);
        parameters.put("dispatcher", "direct");
        reference.setParameters(parameters);

        GenericService genericService = reference.get();
        genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new String[]{key});
        Future<Object> future = RpcContext.getContext().getFuture();
        try {
            Object result = future.get();
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String testInvokeDubbo2MultiRegistry(String key,String registry) {
        RegistryConfig registryConfigItem = new RegistryConfig();
        registryConfigItem.setRegister(false);
        registryConfigItem.setProtocol("nacos");
        registryConfigItem.setAddress("172.16.22.22:8848?namespace=local_weiwei");
        registryConfigItem.setUsername("nacos");
        registryConfigItem.setPassword("expos_nacos");
        registryConfigItem.setId("reg1");
//        registryConfigItem.setZone("reg1");
        registryConfigItem.setWeight(50);

        RegistryConfig registryConfigItem2 = new RegistryConfig();
        registryConfigItem2.setRegister(false);
        registryConfigItem2.setProtocol("nacos");
        registryConfigItem2.setAddress("172.16.22.22:8848?namespace=local_weiwei2");
        registryConfigItem2.setUsername("nacos");
        registryConfigItem2.setPassword("expos_nacos");
//        registryConfigItem.setGroup();
        registryConfigItem.setId("reg2");
//        registryConfigItem2.setZone("reg2");
        registryConfigItem.setWeight(50);

        ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-consumer");
        applicationConfig.setQosEnable(false);
        applicationConfig.setRegisterConsumer(true);

        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.refresh();
        consumerConfig.setRetries(0);
        consumerConfig.setTimeout(3000);

        ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
        reference.setGeneric("true");
        reference.setAsync(true);

        reference.setApplication(applicationConfig);
        reference.setRegistries(Lists.newArrayList(registryConfigItem, registryConfigItem2));
        reference.setConsumer(consumerConfig);

        reference.setInterface("org.springboot3.project.demoapi.DemoService");
        reference.setVersion("1.0");
        reference.setProtocol(CommonConstants.DUBBO);
        reference.setCheck(false);

        Map<String, String> parameters = new HashMap<>(2);
        parameters.put("dispatcher", "direct");
        reference.setParameters(parameters);

        GenericService genericService = reference.get();
//        RpcContext.getContext().setAttachment("registry_zone", registry);
        RpcContext.getContext().setAttachment("registry", registry);
        genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new String[]{key});
        Future<Object> future = RpcContext.getContext().getFuture();
        try {
            Object result = future.get();
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String testInvokeDubbo3(String key) {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-consumer");
//        applicationConfig.setMetadataType("remote");

        // 添加注册中心配置
        RegistryConfig registryConfigItem = new RegistryConfig();
        registryConfigItem.setProtocol("nacos");
        registryConfigItem.setAddress("172.16.22.22:8848?namespace=local_weiwei");
        registryConfigItem.setUsername("nacos");
        registryConfigItem.setPassword("expos_nacos");
        registryConfigItem.setRegisterMode("instance"); // 应用级注册
        registryConfigItem.setUseAsConfigCenter(true);
        registryConfigItem.setUseAsMetadataCenter(true);

        // 添加元数据中心配置
        MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
        metadataReportConfig.setProtocol("nacos");
        metadataReportConfig.setAddress("172.16.22.22:8848?namespace=local_weiwei");
        metadataReportConfig.setUsername("nacos");
        metadataReportConfig.setPassword("expos_nacos");

        ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
        reference.setApplication(applicationConfig);
        reference.setRegistry(registryConfigItem);
        reference.setMetadataReportConfig(metadataReportConfig); // 设置元数据中心配置
        reference.setInterface("org.springboot3.project.demoapi.DemoService");
        reference.setVersion("1.0");
        reference.setGeneric("true");

        // 配置消费者
        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.setThreads(600);
        consumerConfig.setQueues(800);
        consumerConfig.setRetries(0);
        consumerConfig.setTimeout(30000);
        reference.setConsumer(consumerConfig);

        reference.setCheck(false);
        reference.setAsync(true);

        // 获取泛化服务
        GenericService genericService = reference.get();

        // 调用服务
        genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{key});

        // 处理异步结果

        Future<Object> future = RpcContext.getContext().getFuture();
        try {
            Object result = future.get(30000, TimeUnit.MILLISECONDS);
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestService testService = new TestService();

//            String result = testService.testInvokeDubbo2MultiRegistry("word !","reg1");
            String result = testService.testInvokeDubbo2("word !");
            System.out.println();
            System.out.println();
            System.out.println(".............................");
            System.out.println("get result = " + result);
            System.out.println(".............................");
            System.out.println();
            System.out.println();

    }
}
